package com.dq.rbac.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dq.rbac.entity.SysRole;
import com.dq.rbac.entity.SysRoleMenu;
import com.dq.rbac.entity.SysUser;
import com.dq.rbac.entity.SysUserRole;
import com.dq.rbac.entity.vo.PageBean;
import com.dq.rbac.service.SysRoleMenuService;
import com.dq.rbac.service.SysRoleService;
import com.dq.rbac.service.SysUserRoleService;
import com.dq.rbac.vo.R;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @project: rbac
 * @ClassName: SysRoleController
 * @author: Dq
 * @since: 2023/1/27 20:57
 */
@RestController
@RequestMapping("/role")
public class SysRoleController {
    @Resource
    private SysRoleService roleService;
    @Resource
    private SysUserRoleService userRoleService;
    @Resource
    private SysRoleMenuService roleMenuService;

    /**
     * 获取所有角色列表
     *
     * @return
     */
    @GetMapping("/roleList")
    @PreAuthorize("hasAuthority('system:role:query')")
    public R getRoleList() {
        List<SysRole> roles = roleService.list();
        return R.ok().data("roleList", roles);
    }

    /**
     * 分页查询 返回所有角色列表
     *
     * @param pageBean
     * @return
     */
    @PostMapping("/list")
    @PreAuthorize("hasAuthority('system:role:query')")
    public R queryList(@RequestBody PageBean pageBean) {
        String query = pageBean.getQuery().trim(); //去除多余空格的查询条件
        Page<SysRole> page = new Page<>(pageBean.getCurrent(), pageBean.getPageSize());
        Page<SysRole> pageResult = roleService.page(page, new LambdaQueryWrapper<SysRole>().like(StrUtil.isNotBlank(query), SysRole::getName, query));
        List<SysRole> roleList = pageResult.getRecords();
        //返回分页total
        long total = pageResult.getTotal();
        return R.ok().data("roleList", roleList).data("total", total);
    }

    /**
     * 根据id是否提供来判断添加或者修改
     * 权限：add edit
     *
     * @param sysRole
     * @return
     */
    @PostMapping("save")
    @PreAuthorize("hasAuthority('system:role:add')" + "||" + "hasAuthority('system:role:edit')")
    public R save(@RequestBody SysRole sysRole) {
        if (sysRole.getId() == null) { //添加
            sysRole.setCreateTime(new Date());
            roleService.save(sysRole);
            return R.ok().message("角色添加成功");
        }
        //修改
        sysRole.setUpdateTime(new Date());
        boolean success = roleService.updateById(sysRole);
        if (success) {
            return R.ok().message("更新成功");
        } else {
            return R.error().message("修改失败");
        }
    }

    /**
     * 根据id查询角色
     * 用于回显修改时的数据
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAuthority('system:role:query')")
    public R queryById(@PathVariable("id") Long id) {
        SysRole sysRole = roleService.getById(id);
        return R.ok().data("sysRole", sysRole);
    }

    /**
     * 删除角色表
     * role + 用户关联到此角色user的 Col 删除
     *
     * @param ids
     * @return
     */
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('system:role:delete')")
    @Transactional
    public R delete(@RequestBody Long[] ids) {
        //删除角色 + 角色关联的menu 表
        roleService.removeByIds(Arrays.asList(ids));
        boolean success = userRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId, ids));//此ids 是数组 因此采用 where role_id in (id1 , id2 , id3)
        if (success) {
            return R.ok().message("删除成功");
        }else {
            return R.error().message("权限不够,删除失败");
        }

    }

    /**
     * 获取当前角色已经拥有的菜单集合 用于修改权限操作
     *
     * @param roleId
     * @return
     */
    @GetMapping("menus/{roleId}")
    @PreAuthorize("hasAuthority('system:role:menu')")
    public R menus(@PathVariable(value = "roleId") Long roleId) {
        //获取当前角色的权限 ID集合 用于前端组件Tree模型Checked的判断
        List<SysRoleMenu> roleMenuList = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        List<Long> checkedMenuIds = roleMenuList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        return R.ok().data("menuIdList", checkedMenuIds);
    }

    /**
     * 重新修改角色的菜单权限
     *
     * @param roleId 角色id
     * @param ids    菜单权限id
     * @return R
     */
    @Transactional
    @PostMapping("grantMenu/{roleId}")
    @PreAuthorize("hasAuthority('system:role:menu')")
    public R grantMenu(@PathVariable(value = "roleId") Long roleId, @RequestBody Long[] ids) {
        //删除 role_menu的关联表 并重新根据roleId 与 ids 实现重新绑定
        List<SysRoleMenu> sysRoleMenuList = Arrays.stream(ids).map(menuId -> {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(roleId);
            sysRoleMenu.setMenuId(menuId);
            return sysRoleMenu;
        }).collect(Collectors.toList());
        //删除原有关系 role_menu  建立新绑定
        roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        roleMenuService.saveBatch(sysRoleMenuList);
        return R.ok();
    }

}
